package com.gitee.zihaolicn;
import com.strobel.decompiler.Decompiler;
import com.strobel.decompiler.DecompilerSettings;
import com.strobel.decompiler.PlainTextOutput;

import java.io.*;
import java.nio.file.*;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class DecompileWithProcyon {
    public static void main(String[] args) {
        // 输入文件夹（包含 .class 或 .jar 文件）
        String inputPath = "C:\\Users\\li003\\IdeaProjects\\RepoJavaDecompile\\target";
        // 输出文件夹（反编译后的 Java 文件）
        String outputPath = "C:\\Users\\li003\\IdeaProjects\\RepoJavaDecompile\\target\\result";

        try {
            // 确保输出文件夹存在
            Files.createDirectories(Paths.get(outputPath));

            // 遍历输入文件夹
            Files.walk(Paths.get(inputPath))
                    .filter(Files::isRegularFile)
                    .forEach(path -> {
                        String fileName = path.toString();
                        if (fileName.endsWith(".class")) {
                            if(fileName.contains("$")){
                                return;
                            }
                            decompileClassFile(path.toFile(), outputPath);
                        } else if (fileName.endsWith(".jar")) {
                            decompileJarFile(path.toFile(), outputPath);
                        }
                    });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 反编译单个 .class 文件
    private static void decompileClassFile(File classFile, String outputPath) {
        try {
            // 读取 .class 文件的字节码
            byte[] classBytes = Files.readAllBytes(classFile.toPath());

            // 配置 Procyon 设置
            DecompilerSettings settings = DecompilerSettings.javaDefaults();
            settings.setShowSyntheticMembers(false); // 忽略合成成员
            settings.setForceExplicitTypeArguments(true); // 强制使用显式类型参数
            StringWriter stringWriter = new StringWriter();
            PlainTextOutput output = new PlainTextOutput(stringWriter);

            // 执行反编译
            Decompiler.decompile(classFile.getAbsolutePath(), output, settings);

            // 获取类名和包结构
            String className = getClassNameFromFile(classFile);
            String outputFilePath = outputPath + File.separator + className.replace(".", File.separator) + ".java";

            // 确保输出目录存在
            Files.createDirectories(Paths.get(outputFilePath).getParent());

            // 写入反编译后的 Java 文件
            Files.write(Paths.get(outputFilePath), stringWriter.toString().getBytes());
            System.out.println("Decompiled: " + outputFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 反编译 .jar 文件
    private static void decompileJarFile(File jarFile, String outputPath) {
        try (JarFile jar = new JarFile(jarFile)) {
            Enumeration<JarEntry> entries = jar.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                if (entry.getName().endsWith(".class")) {
                    // 读取 .class 文件的字节码
                    InputStream inputStream = jar.getInputStream(entry);
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        byteArrayOutputStream.write(buffer, 0, bytesRead);
                    }
                    byte[] classBytes = byteArrayOutputStream.toByteArray();

                    // 配置 Procyon 设置
                    DecompilerSettings settings = DecompilerSettings.javaDefaults();
                    settings.setShowSyntheticMembers(false); // 忽略合成成员
                    settings.setForceExplicitTypeArguments(true); // 强制使用显式类型参数
                    StringWriter stringWriter = new StringWriter();
                    PlainTextOutput output = new PlainTextOutput(stringWriter);

                    // 执行反编译
                    Decompiler.decompile(entry.getName(), output, settings);

                    // 获取类名和包结构
                    String className = entry.getName().replace("/", ".").replace(".class", "");
                    String outputFilePath = outputPath + File.separator + className.replace(".", File.separator) + ".java";

                    // 确保输出目录存在
                    Files.createDirectories(Paths.get(outputFilePath).getParent());

                    // 写入反编译后的 Java 文件
                    Files.write(Paths.get(outputFilePath), stringWriter.toString().getBytes());
                    System.out.println("Decompiled: " + outputFilePath);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 从 .class 文件路径中提取类名（包含包名）
    private static String getClassNameFromFile(File classFile) throws IOException {
        // 这里简化处理，实际中可能需要解析字节码以获取完整类名
        String path = classFile.getAbsolutePath();
        String basePath = "C:\\Users\\li003\\IdeaProjects\\RepoJavaDecompile\\target"; // 替换为实际的输入文件夹路径
        String relativePath = path.substring(path.indexOf(basePath) + basePath.length() + 1);
        return relativePath.replace(File.separator, ".").replace(".class", "");
    }
}
